package com.zj.eswrapper.interfaces;

import com.zj.eswrapper.enums.OperatorEnum;
import com.zj.eswrapper.enums.ScoreModeEnum;

import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;

import static com.zj.eswrapper.constance.DefaultValueConstance.ALL;

/**
 * 查询拼接器接口
 *
 * @author arthur_zhou
 * @date 2023/12/28 16:10
 */
public interface IEsQueryWrapper<Field,
        QueryWrapper extends IEsQueryWrapper<Field, QueryWrapper, AggWrapper, QueryBuilder, SearchBuilder, AggBuilder>,
        AggWrapper extends IEsAggWrapper<Field, AggWrapper, QueryWrapper, SearchBuilder, AggBuilder>,
        QueryBuilder,
        SearchBuilder,
        AggBuilder>
        extends IBaseWrapper<Field>, IBuilderWrapper<QueryBuilder, SearchBuilder> {

    /**
     * 等于 term
     *
     * @param field 字段名
     * @param val   值
     * @return this
     */
    default QueryWrapper term(Field field, Object val) {
        return term(field, val, null);
    }

    /**
     * 等于 term
     *
     * @param field 字段名
     * @param val   值
     * @param boost 权重
     * @return this
     */
    QueryWrapper term(Field field, Object val, Float boost);

    /**
     * in terms
     *
     * @param field 字段名
     * @param val   值
     * @return this
     */
    default <T> QueryWrapper terms(Field field, T... val) {
        return terms(field, Arrays.asList(val));
    }

    /**
     * in terms
     *
     * @param field 字段名
     * @param val   值
     * @return this
     */

    default QueryWrapper terms(Field field, Collection<?> val) {
        return terms(field, val, null);
    }

    /**
     * in terms
     *
     * @param field 字段名
     * @param val   值
     * @param boost 权重
     * @return this
     */
    QueryWrapper terms(Field field, Collection<?> val, Float boost);

    /**
     * 分词查询
     *
     * @param field 字段名
     * @param val   值
     * @return this
     */
    default QueryWrapper match(Field field, Object val) {
        return match(field, val, null, null);
    }

    /**
     * 分词查询
     *
     * @param field 字段名
     * @param val   值
     * @param boost 权重
     * @return this
     */
    default QueryWrapper match(Field field, Object val, Float boost) {
        return match(field, val, boost, null);
    }

    /**
     * 分词查询
     *
     * @param field    字段名
     * @param val      值
     * @param operator 关系
     * @return this
     */
    default QueryWrapper match(Field field, Object val, OperatorEnum operator) {
        return match(field, val, null, operator);
    }

    /**
     * 分词查询
     *
     * @param field    字段名
     * @param val      值
     * @param boost    权重
     * @param operator 关系
     * @return this
     */
    QueryWrapper match(Field field, Object val, Float boost, OperatorEnum operator);

    /**
     * 前缀匹配
     *
     * @param field 字段名
     * @param val   值
     * @return this
     */
    default QueryWrapper prefix(Field field, String val) {
        return prefix(field, val, null);
    }

    /**
     * 前缀匹配
     *
     * @param field 字段名
     * @param val   值
     * @param boost 权重
     * @return this
     */
    QueryWrapper prefix(Field field, String val, Float boost);

    /**
     * 查全部
     *
     * @return this
     */
    default QueryWrapper matchAll() {
        return matchAll(null);
    }

    /**
     * 查全部
     *
     * @param boost 权重
     * @return this
     */
    QueryWrapper matchAll(Float boost);

    /**
     * 分词匹配
     *
     * @param field 字段名
     * @param val   值
     * @return this
     */
    default QueryWrapper matchPhrase(Field field, String val) {
        return matchPhrase(field, val, null);
    }

    /**
     * 分词匹配
     *
     * @param field 字段名
     * @param val   值
     * @param boost 权重
     * @return this
     */
    QueryWrapper matchPhrase(Field field, String val, Float boost);

    /**
     * 前缀匹配
     *
     * @param field 字段名
     * @param val   值
     * @return this
     */
    default QueryWrapper matchPhrasePrefix(Field field, String val) {
        return matchPhrasePrefix(field, val, null, null);
    }

    /**
     * 前缀匹配
     *
     * @param field 字段名
     * @param val   值
     * @param boost 权重
     * @return this
     */
    default QueryWrapper matchPhrasePrefix(Field field, String val, Float boost) {
        return matchPhrasePrefix(field, val, boost, null);
    }

    /**
     * 前缀匹配
     *
     * @param field         字段名
     * @param val           值
     * @param maxExpansions 最大拓展数
     * @return this
     */
    default QueryWrapper matchPhrasePrefix(Field field, String val, Integer maxExpansions) {
        return matchPhrasePrefix(field, val, null, maxExpansions);
    }

    /**
     * 前缀匹配
     *
     * @param field         字段名
     * @param val           值
     * @param boost         权重
     * @param maxExpansions 最大拓展数
     * @return this
     */
    QueryWrapper matchPhrasePrefix(Field field, String val, Float boost, Integer maxExpansions);


    /**
     * 多字段匹配
     *
     * @param val    值
     * @param fields 字段
     * @return this
     */
    default QueryWrapper multiMatch(String val, Field... fields) {
        return multiMatch(val, null, null, null, fields);
    }

    /**
     * 多字段匹配
     *
     * @param val    值
     * @param boost  权重
     * @param fields 字段
     * @return this
     */
    default QueryWrapper multiMatch(String val, Float boost, Field... fields) {
        return multiMatch(val, boost, null, null, fields);
    }

    /**
     * 多字段匹配
     *
     * @param val      值
     * @param operator 逻辑
     * @param fields   字段
     * @return this
     */
    default QueryWrapper multiMatch(String val, OperatorEnum operator, Field... fields) {
        return multiMatch(val, null, operator, null, fields);
    }

    /**
     * 多字段匹配
     *
     * @param val      值
     * @param operator 逻辑
     * @param boost    权重
     * @param fields   字段
     * @return this
     */
    default QueryWrapper multiMatch(String val, Float boost, OperatorEnum operator, Field... fields) {
        return multiMatch(val, boost, operator, null, fields);
    }

    /**
     * 多字段匹配
     *
     * @param val                值
     * @param operator           逻辑
     * @param boost              权重
     * @param minimumShouldMatch 最小匹配度
     * @param fields             字段
     * @return this
     */
    QueryWrapper multiMatch(String val, Float boost, OperatorEnum operator, String minimumShouldMatch, Field... fields);

    /**
     * 后面的条件转must关系
     *
     * @return this
     */
    default QueryWrapper must() {
        return and();
    }

    /**
     * 后面的条件转should关系
     *
     * @return this
     */
    default QueryWrapper should() {
        return or();
    }

    /**
     * 后面的条件转must_not关系
     *
     * @return this
     */
    default QueryWrapper mustNot() {
        return not();
    }

    /**
     * 后面的条件转must关系
     *
     * @return this
     */
    QueryWrapper and();

    /**
     * 后面的条件转should关系
     *
     * @return this
     */
    QueryWrapper or();

    /**
     * 后面的条件转must_not关系
     *
     * @return this
     */
    QueryWrapper not();

    /**
     * 后面的条件转filter关系
     *
     * @return this
     */
    QueryWrapper filter();

    /**
     * 自定义条件拼接
     *
     * @param query 查询函数
     * @return this
     */
    default QueryWrapper custom(Supplier<QueryBuilder> query) {
        return custom(Objects.nonNull(query) ? query.get() : null);
    }

    /**
     * 自定义条件拼接
     *
     * @param builder 查询类
     * @return this
     */
    QueryWrapper custom(QueryBuilder builder);

    /**
     * 在当前关系里嵌套子条件
     *
     * @param wrapper 拼接器
     * @return this
     */
    QueryWrapper bool(IEsQueryWrapper<?, ?, ?, QueryBuilder, ?, ?> wrapper);

    /**
     * 在当前关系里嵌套子条件
     *
     * @param consumer 函数
     * @return this
     */
    QueryWrapper bool(Consumer<QueryWrapper> consumer);

    /**
     * 嵌套查询
     *
     * @param path     路径信息
     * @param consumer 函数
     * @return this
     */
    default QueryWrapper nested(String path, Consumer<QueryWrapper> consumer) {
        return nested(path, consumer, null);
    }

    /**
     * 嵌套查询
     *
     * @param path      路径信息
     * @param consumer  函数
     * @param scoreMode 匹配子对象的分数相关性分数
     * @return this
     */
    default QueryWrapper nested(String path, Consumer<QueryWrapper> consumer, ScoreModeEnum scoreMode) {
        return nested(path, consumer, scoreMode, null);
    }

    /**
     * 嵌套查询
     *
     * @param path      路径信息
     * @param consumer  函数
     * @param scoreMode 匹配子对象的分数相关性分数
     * @param boost     权重
     * @return this
     */
    QueryWrapper nested(String path, Consumer<QueryWrapper> consumer, ScoreModeEnum scoreMode, Float boost);

    /**
     * 大于
     *
     * @param field 字段名
     * @param val   值
     * @return this
     */
    default QueryWrapper gt(Field field, Object val) {
        return gt(field, val, null);
    }

    /**
     * 大于
     *
     * @param field 字段名
     * @param val   值
     * @param boost 权重
     * @return this
     */
    QueryWrapper gt(Field field, Object val, Float boost);

    /**
     * 大于等于
     *
     * @param field 字段名
     * @param val   值
     * @return this
     */
    default QueryWrapper ge(Field field, Object val) {
        return ge(field, val, null);
    }

    /**
     * 大于等于
     *
     * @param field 字段名
     * @param val   值
     * @param boost 权重
     * @return this
     */
    QueryWrapper ge(Field field, Object val, Float boost);

    /**
     * 小于
     *
     * @param field 字段名
     * @param val   值
     * @return this
     */
    default QueryWrapper lt(Field field, Object val) {
        return lt(field, val, null);
    }

    /**
     * 小于
     *
     * @param field 字段名
     * @param val   值
     * @param boost 权重
     * @return this
     */
    QueryWrapper lt(Field field, Object val, Float boost);

    /**
     * 小于等于
     *
     * @param field 字段名
     * @param val   值
     * @return this
     */
    default QueryWrapper le(Field field, Object val) {
        return le(field, val, null);
    }

    /**
     * 小于等于
     *
     * @param field 字段名
     * @param val   值
     * @param boost 权重
     * @return
     */
    QueryWrapper le(Field field, Object val, Float boost);

    /**
     * 范围
     *
     * @param field 字段名
     * @param ge    大于等于
     * @param le    小于等于
     * @return this
     */
    default QueryWrapper between(Field field, Object ge, Object le) {
        return between(field, ge, le, null);
    }

    /**
     * 范围
     *
     * @param field 字段名
     * @param ge    大于等于
     * @param le    小于等于
     * @param boost 权重
     * @return this
     */
    QueryWrapper between(Field field, Object ge, Object le, Float boost);

    /**
     * 范围，from to可以有一个为空
     *
     * @param field 字段名
     * @param from  大于等于
     * @param to    小于等于
     * @return this
     */
    default QueryWrapper range(Field field, String from, String to) {
        return range(field, from, to, null);
    }

    /**
     * 范围，from to可以有一个为空
     *
     * @param field 字段名
     * @param from  大于等于
     * @param to    小于等于
     * @param boost 权重
     * @return this
     */
    QueryWrapper range(Field field, String from, String to, Float boost);

    /**
     * 范围，check无效 不做校验
     *
     * @param field    字段名
     * @param gt       大于
     * @param gte      大于等于
     * @param lt       小于
     * @param lte      小于等于
     * @param boost    权重
     * @param from     大于等于
     * @param to       小于等于
     * @param format   时间格式
     * @param timeZone 时区
     * @return this
     */
    QueryWrapper range(Field field, Object gt, Object gte, Object lt, Object lte, Float boost,
                       String from, String to, String format, String timeZone);

    /**
     * like wildcard
     *
     * @param field 字段
     * @param val   值，会字段拼接 *val*
     * @return this
     */
    default QueryWrapper wildcard(Field field, String val) {
        return wildcard(field, val, null);
    }

    /**
     * like wildcard
     *
     * @param field 字段
     * @param val   值，会字段拼接 *val*
     * @param boost 权重
     * @return this
     */
    default QueryWrapper wildcard(Field field, String val, Float boost) {
        return wildcard(field, boost, ALL, val, ALL);
    }

    /**
     * like wildcard
     *
     * @param field 字段
     * @param val   手动拼接通配符
     * @return this
     */
    default QueryWrapper wildcard(Field field, String... val) {
        return wildcard(field, null, val);
    }

    /**
     * like wildcard
     *
     * @param field 字段
     * @param boost 权重
     * @param val   手动拼接通配符
     * @return this
     */
    QueryWrapper wildcard(Field field, Float boost, String... val);

    /**
     * 字段存在
     *
     * @param field 字段
     * @return this
     */
    default QueryWrapper exists(Field field) {
        return exists(field, null);
    }

    /**
     * 字段存在
     *
     * @param field 字段
     * @param boost 权重
     * @return this
     */
    QueryWrapper exists(Field field, Float boost);

    /**
     * id查询
     *
     * @param val id
     * @return this
     */
    default QueryWrapper ids(String... val) {
        return ids(Arrays.asList(val));
    }

    /**
     * 字段存在
     *
     * @param val id
     * @return this
     */
    default QueryWrapper ids(Collection<String> val) {
        return ids(val, null);
    }

    /**
     * 字段存在
     *
     * @param boost 权重
     * @param val   id
     * @return this
     */
    QueryWrapper ids(Collection<String> val, Float boost);

    /**
     * 聚合
     *
     * @param wrapper 函数
     * @return this
     */
    QueryWrapper agg(Consumer<AggWrapper> wrapper);
}
